#!/usr/bin/env python
# -*- coding: UTF-8 -*-

#------------------------------------------------------------------------------
# Copyright (c) 2010 Giuseppe Buzzanca (PiDy) <giuseppebuzzanca@gmail.com>.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Contributors:
#     Giuseppe Buzzanca (PiDy) <giuseppebuzzanca@gmail.com>
#         initial API and implementation
#------------------------------------------------------------------------------

import re
from properties import MY_PUNCTUATION, TWITTER_MAX_CHAR, CONSUMER_KEY, \
    CONSUMER_SECRET, TWITTER_UPDATE_URL
import logging
import oauth
from google.appengine.api import urlfetch


def getStringAttachs(attachs):
    """Return the number the characters of the contents of dictionary passed in input, with a the content joined as:

key1: value1 key2: value2 .... keyN: valueN

The pairs keys and values are separated by spaces.
"""
    t = ''
    for d in attachs:
        t = t + ' ' + d['desc'] + ": " + d['link']
    t = t.strip()
    return t

def removeLastWord(str):
    """Return str without the last word and adds three dot. If str contain only one word return None"""
    s = ' '.join(str.split()[:-1])
    if len(s) == 0:
        return None
    else:
        return s + "..."

def joinListWithSpace(*list):
    """Return the list joined with a space, but values empty in list will be ignored and not added, so no double space will be added.

Return an empty string if list is empty or None.
    """
    t = ''
    for w in list:
        if w <> "":
            t = t + ' ' + w
    return t.strip()

def removeEndsPuctuation(str, punctuation):
    """Return the str string without punctuation at the and and stripped."""
    if str:
        while str.endswith(punctuation):
            str = str[:-1]
            # append content to list
            str = str.strip()
    return str

def postTweet(act, u):
    """Makes a request to twitter for update the status.
Gets content from the Activity object passed in input.
If the content exceeds max characters allowed in twitter
the content is reduced, the logic has the following priorities:


1. while attachments are present remove the last word from the description (title or type) of the last attachment.
   If description is empty entire attachment is removed.
2. If all the attachments are removed and the content remove the last word from the main content of the 
   Activity object until the content not exceed the max characters allowed.
    
If geotag points are present in Activity will be added to twitter update.
"""
    if act.getSource() == "tag:twitter.com":
        logging.debug("This entry is a secondary duplicate of an twitter entry primary version, don't tweet it")
        return
    act.content = re.sub(r'&lt;a href="http://www.google.com/profiles/[0-9]+" class="proflink" oid="[0-9]+"&gt;.*&lt;/a&gt;', '', act.content)
    act.content = re.sub(r'@\*+', '', act.content)
    act.removeNewLine()
    act.unescapeContent()
    act.parseContent()
    content = act.content.strip()
    content = removeEndsPuctuation(content, MY_PUNCTUATION)
    # if link to buzz post is present add it to list
    if act.originalLink:
        origLink = "via: " + act.getShortUrl(act.originalLink, bitlyLogin = u.bitlyLogin, bitlyApiKey = u.bitlyApiKey)
    # If attachments is present add it to list, with title if present otherwise with type
    atchs = []
    if act.getAttachs():
        for attach in act.getAttachs():
            if attach["title"]:
                d = {'desc':removeEndsPuctuation(attach['title'], MY_PUNCTUATION), 'link':act.getShortUrl(attach['link'], bitlyLogin = u.bitlyLogin, bitlyApiKey = u.bitlyApiKey)}
            else:
                d = {'desc':attach['type'], 'link':act.getShortUrl(attach['link'], bitlyLogin = u.bitlyLogin, bitlyApiKey = u.bitlyApiKey)}
            atchs.append(d)
            if len(joinListWithSpace(content, getStringAttachs(atchs), origLink)) >= TWITTER_MAX_CHAR:
                break
        while (len(joinListWithSpace(content, getStringAttachs(atchs), origLink)) >= TWITTER_MAX_CHAR) and atchs:
            lastAttach = atchs.pop()
            logging.debug("Remove last word from attachment description:")
            logging.debug(lastAttach)
            lastAttach = {'desc':removeEndsPuctuation(removeLastWord(lastAttach['desc']), MY_PUNCTUATION), 'link':lastAttach['link']}
            if lastAttach['desc']:
                atchs.append(lastAttach)
    while len(joinListWithSpace(content, getStringAttachs(atchs), origLink)) >= TWITTER_MAX_CHAR:
        logging.debug("Remove last word from content:")
        logging.debug(content)
        content = removeEndsPuctuation(removeLastWord(content), MY_PUNCTUATION)
    # Add geolocation if present
    if act.getGeoPoints():
        updateParams = {'status': joinListWithSpace(content, getStringAttachs(atchs), origLink), 'lat': act.getGeoPoints()[0], 'long': act.getGeoPoints()[1]}
    else:
        updateParams = {'status': joinListWithSpace(content, getStringAttachs(atchs), origLink)}
    logging.debug("Post this:")
    logging.debug(updateParams)
    # Update the status of the user in twitter
    twitterClient = oauth.TwitterClient(CONSUMER_KEY, CONSUMER_SECRET, callback_url = None)
    try:
        twitterClient.make_request(url = TWITTER_UPDATE_URL, token = u.twitterUserToken, secret = u.twitterUserSecret, additional_params = updateParams, method = urlfetch.POST)
    except urlfetch.DownloadError:
        logging.error("Error on post update in twitter, urlfetch timeout")
